package com.feib.stms.batch.service;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.feib.stms.batch.dao.MailQueueJdbcDao;
import com.feib.stms.batch.domain.MailQueue;



@Async
@Service("mailJobService")
public class MailJobService implements Serializable {
	

	private static final long serialVersionUID = 0L;

	protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource(name="mailSender")
    private JavaMailSenderImpl mailSender;

    @Resource(name="mailQueueService")
    private MailQueueService mailQueueService;

    @Resource(name="mailQueueSize")
    private Integer mailQueueSize;

    @Resource(name="defaultMailFrom")
    private String defaultMailFrom;

    @Resource(name="defaultMailReturnReceiptTo")
    private String defaultMailReturnReceiptTo;

    @Resource(name="htmlMailImagePath")
    private String htmlMailImagePath;
    
	@Resource(name="mailQueueDao")
	public   MailQueueJdbcDao mailQueueDao;
    
    @Resource(name="txManager")
    private PlatformTransactionManager transactionManager;
    
    public void execute()
    {
        try {

            for (int i=0; i < mailQueueSize; i++)
            {
                MailQueue mailQueue = mailQueueService.getUnSendMail();
                if (null == mailQueue)
                    break;
                
                execute(mailQueue);
            }
        }
        catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    public void execute(Long mailQueuePk)
    {
        try {
            MailQueue mailQueue = mailQueueService.queryByPk(mailQueuePk);
            
            if (null == mailQueue)
                return ;
            
            execute(mailQueue);
        }
        catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }
        
    public void execute(MailQueue mailQueue)
    {
        if (null == mailQueue)
            return ;
        

        // 建立交易的定義，每一次都是新的 Transaction
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);

        TransactionStatus status = this.transactionManager.getTransaction(definition);

        try {
            // 更新狀態為發送中
            mailQueue.setMailStatus(new Integer(10));
            mailQueueService.updateMailStatus(mailQueue);
        }
        catch (Exception e) {            
            logger.error(e.getMessage(),  e);            
            transactionManager.rollback(status);
            status = null; // roll back 不需要再呼叫 commit
            throw new RuntimeException(e);
        }
        if (null != status)
            transactionManager.commit(status);
        
        
        try
        {
            send(mailQueue);
            //發送成功
            mailQueue.setMailStatus(new Integer(20));
        }
        catch(Exception ex)
        {
            //發送失敗
            mailQueue.setMailStatus(new Integer(30));
            logger.error("發送失敗", ex);
        }
        finally
        {
            status = this.transactionManager.getTransaction(definition);
            
            try {
                mailQueueService.updateMailStatus(mailQueue);
            }
            catch (Exception e) {            
                logger.error(e.getMessage(),  e);            
                transactionManager.rollback(status);
                status = null; // roll back 不需要再呼叫 commit
                throw new RuntimeException(e);
            }
            if (null != status)
                transactionManager.commit(status);
        }
    }

    /**
     * 發送郵件
     * @param mailQueue 代處理郵件
     * @throws MessagingException
     * @throws IOException 
     */
    public void send(MailQueue mailQueue) throws MessagingException, IOException
    {
        MimeMessage mimemessage = mailSender.createMimeMessage();

        if (StringUtils.isNotEmpty(mailQueue.getMailReturnReceiptTo()))
            mimemessage.setHeader("Return-Receipt-To", mailQueue.getMailReturnReceiptTo());
        else if (StringUtils.isNotEmpty(defaultMailReturnReceiptTo))
            mimemessage.setHeader("Return-Receipt-To", defaultMailReturnReceiptTo);

        MimeMessageHelper helper = new MimeMessageHelper(mimemessage, true, "UTF-8");

        if (StringUtils.isNotEmpty(mailQueue.getMailFrom()))
            helper.setFrom(mailQueue.getMailFrom());
        else
            helper.setFrom(defaultMailFrom);            

        // 多個收件者
        String[] tos = StringUtils.split(mailQueue.getMailTo(), ",");
        helper.setTo(tos);

        helper.setSubject(mailQueue.getMailSubject());

        helper.setText(FileUtils.readFileToString(new File(mailQueue.getMailContent()),"UTF-8"), true);

        String inlineResource = mailQueue.getInlineResource();
        if (StringUtils.isNotEmpty(inlineResource))
        {
            String[] rs = inlineResource.split(";");
            for(String s :rs)
            {
                if (null != s && 0 != s.length())
                {
                    String[] cids = s.split(":");
                    FileSystemResource res01 = new FileSystemResource(new File(htmlMailImagePath + cids[1]));
                    helper.addInline(cids[0], res01);
                }
            }
        }
        
        mailSender.send(mimemessage);

    }
    
    public void createAndSend(MailQueue mailQueue) throws Exception{
    	
    	
        // 建立交易的定義，每一次都是新的 Transaction
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        TransactionStatus status = transactionManager.getTransaction(definition);
        try {
        	logger.debug("mailQueue  {}", mailQueue.toString());
            mailQueueDao.insert(mailQueue);
        }
        catch (Exception e2) {
            transactionManager.rollback(status);
            status = null; // roll back 不需要再呼叫 commit
            logger.debug("e2  {}", e2);
            
        }
        if (null != status)
            transactionManager.commit(status);

        // 立即發送
        logger.debug("立即發送 Mail 給  {}", mailQueue.getMailTo());
        execute(mailQueue.getMailQueuePk());
        mailQueue = null; // free resource

    	
    	
    }
    
    

}
